//
//  OPKApplePay.m
//
//  Created by ycgame on 2020/4/22.
//  Copyright © 2020 maqianzheng. All rights reserved.
//

#import "ApplePay.h"
#import "OPKStoreManager.h"
#import "OPKStoreObserver.h"
#import "OpenSDK_LoginManager.h"
#import "OpenSDK_EventManager.h"
#import "OpenSDK_EventKeys.h"
#import "OpenSDK_Toast.h"
#import "OpenSDK_Toast.h"
#import "OpenSDK_PayManager.h"
#import "OPKConfiguration.h"
#import "OpenSDK_HttpUtil.h"
#import "OpenSDK_JsonUtil.h"
#import "OpenSDK_DataKeys.h"
#import "OpenSDK_Loading.h"
#import "OpenSDK_ReqDataGenerator.h"
#import "OpenSDK_StatisticsManager.h"
#import "OPKAppleOrderResponseModel.h"
#import "OPKKeychainItem.h"
#import "OPKLoadingView.h"
#import "OPKGameRoleModel.h"
#import "OpenSDK_UIUtil.h"

@class OPKOrderItem;

@interface ApplePay()
// key: productId, value: SKPayment
@property(strong)NSMutableDictionary *products;
// key: productId, value: status.    status: 0-未开始，1-正常，2-已结束
@property(strong)NSMutableDictionary *promoProducts;

@property(nonatomic, strong)OpenSDK_PayResData *currentPayInfo;
@end

@interface OPKOrderItem(ToUser)
- (OpenSDK_OrderInfo *)toOrderInfo;
@end

@implementation ApplePay

#pragma mark - OpenSDK_SdkProtrol声明方法
-(void) initInfo {
    _products = [[NSMutableDictionary alloc] initWithCapacity:0];
    _promoProducts = [[NSMutableDictionary alloc] initWithCapacity:0];
    // TODO: 测试数据
    //    [_promoProducts setValue:@"1" forKey:@"com.ycgames.dmc.12"];
    
    //用户登录成功后进行初始化
    [OpenSDK_EventManager addObsver:self selector:@selector(initSDK:) name:OPENSDK_EVENT_LOGIN_SUCCESS object:nil className:@"ApplePay"];
    [OpenSDK_EventManager addObsver:self selector:@selector(enteredGame:) name:OPENSDK_ENTERED_GAME object:nil className:@"ApplePay"];
    [OpenSDK_EventManager addObsver:self selector:@selector(applicationDidFinishLaunch:) name:OPENSDK_EVENT_APPLICATION_DIDFINISHLAUNCHINGWITHOPTIONS object:nil className:@"ApplePay"];
    [OpenSDK_EventManager addObsver:self selector:@selector(applicationWillTerminate:) name:OPENSDK_EVENT_APPLICATION_WILL_TERMINATE object:nil className:@"ApplePay"];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleProductRequestNotification:)
                                                 name:OPKProductRequestNotification
                                               object:[OPKStoreManager sharedInstance]];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleConfirmTransactionNotification:)
                                                 name:OPKConfirmTransactionNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleFailedTransactionNotification:)
                                                 name:OPKFailedTransactionNotification
                                               object:nil];
}

#pragma mark - OpenSDK_SdkProtrol声明方法 - 服务器唯一标识
-(NSString *) getServerName {
    return @"ApplePay";
}

#pragma mark - OpenSDK_PayProtocol声明方法 - 展示的图标
-(NSString *) getDisplayIcon {
    return @"op_pay_apple.png";
}

#pragma mark - OpenSDK_PayProtocol声明方法 - 展示的名字
-(NSString *) getDisplayName {
    return @"苹果支付";
}

#pragma mark - OpenSDK_PayProtocol声明方法 - 支付平台名
-(NSString *) getPlatform {
    return @"ApplePay";
}

#pragma mark - OpenSDK_PayProtocol声明方法 - 支付平台版本号
-(NSString *) getPlatformVersion {
    return @"V1_";
}

#pragma mark - OpenSDK_PayProtocol声明方法 - 统计的类型名
-(NSString *) getStatisticsType {
    return @"APPLE";
}

#pragma mark - OpenSDK_PayProtocol声明方法 - 调起第三方平台支付，传入opensdk订单号
-(void) startPay:(OpenSDK_PayResData *) opensdkOrder {
    
    // 将当前订单信息存入内存
    _currentPayInfo = opensdkOrder;
    /// 当商品列表为空
    if (_products == nil || [_products count] == 0) {
        [[OpenSDK_PayManager getInstance] callbackPayFail:@"商品信息无效，请检查网络连接，稍后重试" withOrder:nil];
        // 请求商品列表
        [self fetchProductsShouldCallBackWhenFailed:true];
        return;
    }
    
    // 获取商品id
    NSString *productId = [opensdkOrder getProduct];
    // 根据商品id查找对应商品
    SKProduct* selectedProduct = [_products objectForKey:productId];
    // productId没有对应的商品信息，说明productId非法
    if(selectedProduct == nil) {
        [[OpenSDK_PayManager getInstance] callbackPayFail:@"抱歉，商品异常无法支付" withOrder:nil];
        return;
    }
    
    // 用户id不能为空
    NSString *uid = [[OpenSDK_LoginManager getInstance] curOpenId];
    if (uid == nil || uid.length == 0) {
        [[OpenSDK_PayManager getInstance] callbackPayFail:@"抱歉，用户信息异常" withOrder:nil];
        return;
    }
    
    //进行applePay的支付
    NSLog(@"开始ApplePay!product_id=%@,order_id=%@", productId, [opensdkOrder getOrderID]);
    
    // 创建OPK订单对象
    OPKOrderItem *order = [[OPKOrderItem alloc] init];
    order.uid = uid;
    order.orderId = opensdkOrder.getOrderID;
    order.appData = opensdkOrder.getAppData;
    order.productId = productId;
    order.productAmount = opensdkOrder.getProductAmount;
    order.currency = opensdkOrder.getCurrency;
    order.payStatus = opensdkOrder.getPayStatus;
    order.payTime = [NSString stringWithFormat:@"%ld", opensdkOrder.getPayTime];
    // 是否为订阅商品
    if (@available(iOS 12.0, *)) {
        order.isSubscriptionProduct = (selectedProduct.subscriptionGroupIdentifier != nil);
    } else {
        // iOS12以下，暂无法分辨订阅
    }
    // 调用购买
    [[OPKStoreObserver sharedInstance] buy:selectedProduct order:order];
    
    [OPKLoadingView start];
}

#pragma mark - 监听事件方法
- (void)initSDK:(NSNotification *)notification {
    // 将uid存入钥匙串
    [OPKKeychainItem setUid:[[OpenSDK_LoginManager getInstance] curOpenId]];
}

// 进入游戏
- (void)enteredGame:(NSNotification *)notification {
    // TODO: 测试次数
    //    [self setCurrentUserLocalUsedCount:0 productId:@"com.ycgames.dmc.12"];
    // 内存中存在，则不重复获取
    if (_products != nil && _products.count > 0) { return; }
    [self fetchProductsShouldCallBackWhenFailed:false];
}

- (void)applicationWillTerminate:(NSNotification *)notification {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:OPKProductRequestNotification object:[OPKStoreManager sharedInstance]];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:OPKConfirmTransactionNotification object:nil];
    [[OPKStoreObserver sharedInstance] resignTransactionObserver];
}

#pragma mark - 请求商品信息
/// 服务器获取商品列表
- (void)fetchProductsShouldCallBackWhenFailed:(BOOL)isCall {
    [OpenSDK_HttpUtil getProductIds:^(OpenSDK_BaseResData *resData) {
        if([resData isOk]) {
            // 正常商品
            NSArray *products = [resData.content objectForKey:@"products"];
            NSLog(@"opensdk返回商品列表,products=%@", products);
            NSMutableSet *productItems=[[NSMutableSet alloc] init];
            if (products) {
                for (NSDictionary *item in products) {
                    [productItems addObject:[item objectForKey:@"product_id"]];
                }
            }
            if (productItems.count > 0) {
                /// 向苹果请求商品id列表
                [[OPKStoreManager sharedInstance] startProductRequestWithIdentifiers:[productItems allObjects]];
            }
            // 兑换商品
            NSArray *promoProducts = [resData.content objectForKey:@"exchangeCodes"];
            NSLog(@"opensdk返回兑换商品列表,products=%@", promoProducts);
            if (promoProducts) {
                for (NSDictionary *item in promoProducts) {
                    NSString *status = [item objectForKey:@"status"] ?: OPKPromoProductStatusNotStarted;
                    NSString *productId = [item objectForKey:@"product_id"];
                    [self.promoProducts setValue:status forKey:productId];
                }
            }
            // 监听苹果支付队列
            [[OPKStoreObserver sharedInstance] becomeTransactionObserver];
        } else {
            if (isCall) {
                [[OpenSDK_PayManager getInstance] callbackPayFail:@"获取商品列表失败，请稍后重试" withOrder:nil];
            }
        }
    }];
    // 测试
    //    NSArray *ids = @[@"pay_test_amount_6",
    //                     @"pay_test_amount_12",
    //                     @"pay_test_amount_18",
    //                     @"pay_subscription_test_amount_8",
    //                     @"pay_subscription_test_amount_30",
    //                     @"pay_subscription_test_amount_88",
    //                     @"pay_super_subscription_test_amount_8"];
    //    [[OPKStoreManager sharedInstance] startProductRequestWithIdentifiers:ids];
}

#pragma mark - 商品请求通知
- (void)handleProductRequestNotification:(NSNotification *)notification {
    OPKStoreManager *storeManager = (OPKStoreManager*)notification.object;
    // 将苹果返回商品列表放入内存
    for (SKProduct *p in storeManager.products) {
        [_products setValue:p forKey:p.productIdentifier];
    }
}

#pragma mark - 收到需要去服务器验证订单的通知
- (void)handleConfirmTransactionNotification:(NSNotification *)notification {
    NSLog(@"【PAY】收到Apple Observer返回成功通知");
    // 所有商品
    NSArray<OPKTransactionItem*> *allTransactionItems = (NSArray<OPKTransactionItem*> *)notification.object;
    // 如果兑换商品为空，则正常支付
    if (_promoProducts.allKeys.count == 0) {
        [self handleConfirmTransactions:allTransactionItems];
    } else {
        // 兑换商品
        NSMutableArray<OPKTransactionItem*> *promoTransactionItems = [[NSMutableArray alloc] initWithCapacity:0];
        // 过期兑换商品
        NSMutableArray<OPKTransactionItem*> *expiredPromoTransactionItems = [[NSMutableArray alloc] initWithCapacity:0];
        // 正常购买商品
        NSMutableArray<OPKTransactionItem*> *purchasedTransactionItems = [[NSMutableArray alloc] initWithCapacity:0];
        // 遍历分开促销商品与正常购买商品
        for (OPKTransactionItem *item in allTransactionItems) {
            if ([_promoProducts.allKeys containsObject:item.orderItem.productId]) {
                NSString *status = [_promoProducts objectForKey:item.orderItem.productId];
                // 正常期限内的兑换商品
                if ([status isEqualToString:OPKPromoProductStatusAvailable]) {
                    [promoTransactionItems addObject:item];
                } else if ([status isEqualToString:OPKPromoProductStatusExpired]) {
                    [expiredPromoTransactionItems addObject:item];
                } else {
                    // 未开始，不作处理
                }
            } else {
                // 正常商品验证
                [purchasedTransactionItems addObject:item];
            }
        }
        // 正常购买商品则正常处理
        if (purchasedTransactionItems.count > 0) {
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                [self handleConfirmTransactions:[purchasedTransactionItems copy]];
            });
        }
        // 如果有待验证的兑换商品，弹框跟用户确认
        if (promoTransactionItems.count > 0) {
            [self handlePromoTransactions:[promoTransactionItems copy]];
        }
        // 如果有已过期的兑换商品，弹框跟用户确认
        if (expiredPromoTransactionItems.count > 0) {
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                [self handleExpiredPromoTransactions:[expiredPromoTransactionItems copy]];
            });
        }
        
        if (purchasedTransactionItems.count == 0 && promoTransactionItems.count == 0 && expiredPromoTransactionItems.count == 0) {
            [OPKLoadingView stop];
        }
    }
}

#pragma mark - 处理商品逻辑

// 处理兑换商品验证
- (void)handlePromoTransactions:(NSArray<OPKTransactionItem*> *)transactionItems {
    // 判断当前账号使用兑换码次数是否大于0
    UInt8 usedCount = [self currentUserLocalUsedCount:transactionItems];
    // 如果该账号使用兑换码次数大于0，则提示用户不能重复兑换
    if (usedCount > 0) {
        [self handleReusePromoTransactions];
        return;
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:OPKPromoCodeUseAlertMessage preferredStyle:UIAlertControllerStyleAlert];
        // 下次兑换
        UIAlertAction *nextAction = [UIAlertAction actionWithTitle:OPKPromoCodeUseAlertNext style:UIAlertActionStyleDefault handler:nil];
        // 立即兑换
        UIAlertAction *okAction = [UIAlertAction actionWithTitle:OPKPromoCodeUseAlertNow style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            // 前往服务器验证
            [self handleConfirmPromoTransactions:transactionItems];
        }];
        [alertController addAction:nextAction];
        [alertController addAction:okAction];
        [[OpenSDK_UIUtil currentViewController] presentViewController:alertController animated:YES completion:nil];
    });
}

// 处理重复使用兑换码交易
- (void)handleReusePromoTransactions {
    // 点击不再兑换的次数
    UInt8 discardCount = [self currentUserLocalDiscardCount];
    // 次数大于0，则不提示
    if (discardCount > 0) {
        NSLog(@"【PAY】该用户已点击不再兑换");
        return;
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:OPKPromoCodeReuseAlertMessage preferredStyle:UIAlertControllerStyleAlert];
        // 不再兑换
        UIAlertAction *discardAction = [UIAlertAction actionWithTitle:OPKPromoCodeReuseAlertDiscard style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [self setCurrentUserLocalDiscardCount:1];
        }];
        // 了解了
        UIAlertAction *okAction = [UIAlertAction actionWithTitle:OPKPromoCodeReuseAlertOk style:UIAlertActionStyleDefault handler:nil];
        [alertController addAction:discardAction];
        [alertController addAction:okAction];
        [[OpenSDK_UIUtil currentViewController] presentViewController:alertController animated:YES completion:nil];
    });
}

// 处理过期的兑换码
- (void)handleExpiredPromoTransactions:(NSArray<OPKTransactionItem*> *)transactionItems {
    for (OPKTransactionItem *item in transactionItems) {
        // 该笔交易确认失败（过期）
        [[OPKStoreObserver sharedInstance] confirmTransactionWithItem:item result:OPKTransactionResultFail];
    }
}

#pragma mark - 服务器验证

// 商品验证
- (void)handleConfirmTransactions:(NSArray<OPKTransactionItem*> *)transactionItems {
    // 将传过来的交易对象处理为请求服务器的参数格式
    NSDictionary *localInfo = [self confirmTransactionsParamsWithTransactionItems:transactionItems];
    NSLog(@"【PAY】OpenSDK验证请求：%@", localInfo);
    if (localInfo == nil) { return; }
    // 生成最终数据
    NSString *localInfoStr = [OpenSDK_ReqDataGenerator generateDataByDictionary:[localInfo mutableCopy]];
    // 请求验证交易
    [OpenSDK_HttpUtil checkAppleOrderWithParams:localInfoStr httpDelegate:^(OpenSDK_BaseResData *resData) {
        NSLog(@"【PAY】OpenSDK验证结果：%@", resData.content);
        // CheckOrdet返回ok，检查订单状态
        if ([resData isOk]) {
            OPKAppleOrderResponseModel *responseModel = [[OPKAppleOrderResponseModel alloc] initWithData:[resData content]];
            // 验证成功的订单
            [self handlePurchasedOrder:responseModel.purchasedTransactions];
            // 验证失败的
            [self handleFailedOrder:responseModel.failedTransactions];
            // 无法确定结果的
            [self handleUndeterminedOrder:responseModel.undeterminedTransactions];
            
        } else {
            OPKTransactionItem *currentTransactionItem = nil;
            for (OPKTransactionItem *transactionItem in transactionItems) {
                // 统计checkOrder网络失败
                [[OpenSDK_StatisticsManager getInstance]
                 collectPayFailWithType:OPENSDK_STATS_PAY_SUB_CHECK_FAIL
                 orderId:transactionItem.orderItem.orderId
                 cpOrderId:transactionItem.orderItem.appData
                 detail:[self getStatisticsType]
                 failInfo:[resData errorMsg]];
                
                // 如果是当前订单
                if ([[self.currentPayInfo getProduct] isEqualToString:transactionItem.orderItem.productId]) {
                    currentTransactionItem = transactionItem;
                }
            }
            // 如果是当前订单，则回调OpenSDK_PayManager失败
            if (currentTransactionItem != nil) {
                [OPKLoadingView stop];
                NSString *errorNum = @"错误码: unknown";
                NSString *errorMsg = @"错误信息: unknown";
                NSString *errorNo = [NSString stringWithFormat:@"%ld",[resData errorNo]];
                if(errorNo!=nil)
                    errorNum = [@"错误码: " stringByAppendingString:errorNo];
                if([resData errorMsg]!=nil)
                    errorMsg = [@"错误信息: " stringByAppendingString:[resData errorMsg]];
                NSString *errorInfo=[errorNum stringByAppendingString:errorMsg];
                [[OpenSDK_PayManager getInstance] callbackPayFail:errorInfo withOrder:nil];
            }
        }
    }];
}
// 兑换商品验证
- (void)handleConfirmPromoTransactions:(NSArray<OPKTransactionItem*> *)transactionItems {
    // 将传过来的交易对象处理为请求服务器的参数格式
    NSDictionary *localInfo = [self confirmTransactionsParamsWithTransactionItems:transactionItems];
    NSLog(@"【PAY】OpenSDK兑换商品验证请求：%@", localInfo);
    if (localInfo == nil) { return; }
    // 生成最终数据
    NSString *localInfoStr = [OpenSDK_ReqDataGenerator generateDataByDictionary:[localInfo mutableCopy]];
    // 请求验证交易
    [OpenSDK_HttpUtil checkApplePromoOrderWithParams:localInfoStr httpDelegate:^(OpenSDK_BaseResData *resData) {
        NSLog(@"【PAY】OpenSDK兑换商品验证结果：%@", resData.content);
        // CheckOrdet返回ok，检查订单状态
        if ([resData isOk]) {
            OPKAppleOrderResponseModel *responseModel = [[OPKAppleOrderResponseModel alloc] initWithData:[resData content]];
            // 验证成功的订单
            [self handlePromoPurchasedOrder:responseModel.purchasedTransactions];
            // 验证失败的
            [self handlePromoFailedOrder:responseModel.failedTransactions];
            // 验证为重复兑换
            [self handlePromoReusedOrder:responseModel.reusedTransactions];
            // 验证为过期兑换
            [self handlePromoExpiredOrder:responseModel.expiredTransactions];
            // 无法确定结果的不处理
        } else {
            // 请求失败不作处理
        }
    }];
}

- (void)handleFailedTransactionNotification:(NSNotification *)notification {
    [OPKLoadingView stop];
    [[OpenSDK_PayManager getInstance] callbackPayFail:@"支付失败，请重试。" withOrder:nil];
}


#pragma mark - 处理服务器验证结果

/// 处理验证成功的订单
- (void)handlePurchasedOrder:(NSArray <OPKAppleOrderResultModel *>*)results {
    if (results == nil || results.count == 0) { return; }
    // 验证通过
    OPKAppleOrderResultModel *currentPurchasedModel = nil;
    for (OPKAppleOrderResultModel *model in results) {
        // 获取交易对象
        OPKTransactionItem *transactionItem = [[OPKStoreObserver sharedInstance] transactionItemForId:model.transactionId];
        // 向OPKStoreObserver确认订单成功
        [[OPKStoreObserver sharedInstance] confirmTransactionWithItem:transactionItem result:OPKTransactionResultPass];
        // 统计checkOrder成功
        [[OpenSDK_StatisticsManager getInstance]
         collectPaySuccessWithType:OPENSDK_STATS_PAY_SUB_CHECK_SUCCESS
         orderId:model.payInfo.getOrderID
         cpOrderId:model.payInfo.getAppData
         detail:[self getStatisticsType]];
        
        // 完成该笔订单请求次数统计
        NSString *repeatKey = [self orderRepeatKeyWithUid:transactionItem.orderItem.uid transactionId:transactionItem.transactionId];
        [self finishOrderRepeatForKey:repeatKey];
        
        // 如果是当前订单，则回调OpenSDK_PayManager成功
        if ([[self.currentPayInfo getProduct] isEqualToString:transactionItem.orderItem.productId]) {
            currentPurchasedModel = model;
        }
    }
    // 如果是当前订单，则回调OpenSDK_PayManager成功
    if (currentPurchasedModel != nil) {
        [OPKLoadingView stop];
        [[OpenSDK_PayManager getInstance] callbackPaySuccess:nil withOrder:[currentPurchasedModel.payInfo toUserOrderInfo]];
    }
}

/// 处理验证失败订单
- (void)handleFailedOrder:(NSArray <OPKAppleOrderResultModel *>*)results {
    OPKAppleOrderResultModel *currentFailedModel = nil;
    // 验证失败
    for (OPKAppleOrderResultModel *model in results) {
        // 获取交易对象
        OPKTransactionItem *transactionItem = [[OPKStoreObserver sharedInstance] transactionItemForId:model.transactionId];
        // 向OPKStoreObserver确认订单失败
        [[OPKStoreObserver sharedInstance] confirmTransactionWithItem:transactionItem result:OPKTransactionResultFail];
        // 统计checkOrder失败
        [[OpenSDK_StatisticsManager getInstance]
         collectPayFailWithType:OPENSDK_STATS_PAY_SUB_CHECK_FAIL
         orderId:transactionItem.orderItem.orderId
         cpOrderId:transactionItem.orderItem.appData
         detail:[self getStatisticsType]
         failInfo:@"Order status is FAIL"];
        
        // 完成该笔订单请求次数统计
        NSString *repeatKey = [self orderRepeatKeyWithUid:transactionItem.orderItem.uid transactionId:transactionItem.transactionId];
        [self finishOrderRepeatForKey:repeatKey];
        
        // 如果是当前订单，则回调OpenSDK_PayManager失败
        if ([[self.currentPayInfo getProduct] isEqualToString:transactionItem.orderItem.productId]) {
            currentFailedModel = model;
        }
    }
    // 如果是当前订单，则回调OpenSDK_PayManager失败
    if (currentFailedModel != nil) {
        [OPKLoadingView stop];
        [[OpenSDK_PayManager getInstance] callbackPayFail:@"抱歉，支付凭证无效，支付失败" withOrder:[currentFailedModel.payInfo toUserOrderInfo]];
    }
}

/// 验证不确定结果的订单
- (void)handleUndeterminedOrder:(NSArray <OPKAppleOrderResultModel *>*)results {
    //
    OPKTransactionItem *currentUndeterminedTransactionItem = nil;
    
    for (OPKAppleOrderResultModel *model in results) {
        // 获取交易对象
        OPKTransactionItem *transactionItem = [[OPKStoreObserver sharedInstance] transactionItemForId:model.transactionId];
        // 统计checkOrder为PAY_WAIT_CHECK状态
        [[OpenSDK_StatisticsManager getInstance]
         collectPayFailWithType:OPENSDK_STATS_PAY_SUB_CHECK_FAIL
         orderId:model.payInfo.getOrderID
         cpOrderId:model.payInfo.getAppData
         detail:[self getStatisticsType]
         failInfo:@"Order status is NEW"];
        
        // 增加该笔订单请求次数
        NSString *repeatKey = [self orderRepeatKeyWithUid:transactionItem.orderItem.uid transactionId:transactionItem.transactionId];
        [self addOrderRepeatForKey:repeatKey count:1];
        
        // CheckOrder是NeW状态，则回调游戏OpenSDK_PAY_WAIT_CHECK，不移除订单，等待下次Apple回调此订单
        if ([[self.currentPayInfo getProduct] isEqualToString:transactionItem.orderItem.productId]) {
            currentUndeterminedTransactionItem = transactionItem;
        }
    }
    // CheckOrder是NeW状态，则回调游戏OpenSDK_PAY_WAIT_CHECK，不移除订单，等待下次Apple回调此订单
    if (currentUndeterminedTransactionItem != nil) {
        [OPKLoadingView stop];
        OpenSDK_OrderInfo *userOrderInfo = [currentUndeterminedTransactionItem.orderItem toOrderInfo];
        [[OpenSDK_PayManager getInstance] callbackPayWaitCheck:userOrderInfo];
    }
}

// 兑换商品成功处理
- (void)handlePromoPurchasedOrder:(NSArray <OPKAppleOrderResultModel *>*)results {
    if (results == nil || results.count == 0) { return; }
    // 验证通过
    for (OPKAppleOrderResultModel *model in results) {
        OPKTransactionItem *item = [[OPKStoreObserver sharedInstance] transactionItemForId:model.transactionId];
        // 设置改账号兑换次数
        UInt8 count = [self currentUserLocalUsedCountWithProductId:item.orderItem.productId];
        [self setCurrentUserLocalUsedCount:count + 1 productId:item.orderItem.productId];
        [[OPKStoreObserver sharedInstance] confirmTransactionWithId:model.transactionId result:OPKTransactionResultPass];
    }
}

// 兑换商品失败处理
- (void)handlePromoFailedOrder:(NSArray <OPKAppleOrderResultModel *>*)results {
    if (results == nil || results.count == 0) { return; }
    // 验证失败
    for (OPKAppleOrderResultModel *model in results) {
        [[OPKStoreObserver sharedInstance] confirmTransactionWithId:model.transactionId result:OPKTransactionResultFail];
    }
}

// 重复兑换处理
- (void)handlePromoReusedOrder:(NSArray <OPKAppleOrderResultModel *>*)results {
    if (results == nil || results.count == 0) { return; }
    [self handleReusePromoTransactions];
}

// 兑换商品过期处理
- (void)handlePromoExpiredOrder:(NSArray <OPKAppleOrderResultModel *>*)results {
    if (results == nil || results.count == 0) { return; }
    for (OPKAppleOrderResultModel *model in results) {
        // 该笔交易确认失败（放弃）
        [[OPKStoreObserver sharedInstance] confirmTransactionWithId:model.transactionId result:OPKTransactionResultFail];
    }
}


#pragma mark - 参数生成
// 确认交易请求参数
- (NSDictionary *)confirmTransactionsParamsWithTransactionItems:(NSArray<OPKTransactionItem*> *)transactionItems {
    if (transactionItems == nil || transactionItems.count == 0) { return nil; }
    NSString *receipt = [self receipt];
    if (receipt == nil || [receipt length] == 0) { return nil; }
    
    NSMutableDictionary *localInfo=[OpenSDK_ReqDataGenerator generateInitDataWithInfo];
    [localInfo setObject:[self receipt] forKey:@"receipt"];
    [localInfo setObject:[self getPlatform] forKey:OpenSDK_S_PLATFORM];
    [localInfo setObject:[self getPlatformVersion] forKey:OpenSDK_S_PLATFORM_VERSION];
    NSMutableArray *transactionParams = [[NSMutableArray alloc] initWithCapacity:0];
    for (OPKTransactionItem *transactionItem in transactionItems) {
        if (transactionItem.transactionId == nil || transactionItem.orderItem.uid == nil) { continue; }
        // ...
        NSString *transactionId = transactionItem.transactionId == nil ? @"" : transactionItem.transactionId;
        NSString *uid = transactionItem.orderItem.uid == nil ? @"" : transactionItem.orderItem.uid;
        NSString *orderId = transactionItem.orderItem.orderId == nil ? @"" : transactionItem.orderItem.orderId;
        NSString *productId = transactionItem.orderItem.productId == nil ? @"" : transactionItem.orderItem.productId;
        
        NSString *repeatKey = [self orderRepeatKeyWithUid:uid transactionId:transactionId];
        NSNumber *repeat = [self orderRepeatForKey:repeatKey];
        
        NSDictionary *transactionInfo;
        // 如果是兑换商品 则添加几个字段
        if ([_promoProducts.allKeys containsObject:productId]) {
            NSString *appData = [self promoAppData];
            if (appData == nil) {
                NSLog(@"【PAY】Promo appData为空！");
                continue;
            }
            NSString *currency = [self currency];
            transactionInfo = @{@"transactionId": transactionId,
                                @"uid": uid,
                                @"orderId": orderId,
                                @"productId": productId,
                                @"repeat" : repeat,
                                @"appData": appData,
                                @"currency": currency};
        } else {    // 正常支付订单字段
            transactionInfo = @{@"transactionId": transactionId,
                                @"uid": uid,
                                @"orderId": orderId,
                                @"productId": productId,
                                @"repeat" : repeat};
        }
        [transactionParams addObject:transactionInfo];
    }
    if (transactionParams.count == 0) { return nil; }
    [localInfo setObject:transactionParams forKey:@"transactions"];
    return localInfo;
}

- (NSString *)promoAppData {
    NSString *roleId = [OpenSDK getInstance].currentGameRole.roleId;
    NSString *zoneId = [OpenSDK getInstance].currentGameRole.zoneId;
    if (roleId == nil || zoneId == nil) {
        NSLog(@"【PAY】：角色信息为空！");
        return nil;
    }
    NSString *roleLevel = [OpenSDK getInstance].currentGameRole.roleLevel ?: @"";
    NSString *roleName = [OpenSDK getInstance].currentGameRole.roleName ?: @"";
    NSString *roleBalance = [OpenSDK getInstance].currentGameRole.roleBalance ?: @"";
    NSDictionary *dict = @{@"roleId": roleId,
                           @"roleGrade": roleLevel,
                           @"roleName": roleName,
                           @"roleBalance": roleBalance,
                           @"serverId": zoneId};
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];
    if (error) {
        return @"";
    }
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    return jsonString;
}

- (NSString *)currency {
    NSDictionary *mainInfo = [NSBundle mainBundle].infoDictionary;
    NSString *currency = [[mainInfo objectForKey:@"OpenSDKConfig"] objectForKey:@"OpenSDK_Currency"];
    if (currency == nil || currency.length == 0) {
        return @"CNY";
    }
    return currency;
}


#pragma mark - 一些数据读写生成处理

/// 生成存储订单重复次数的key
- (NSString *)orderRepeatKeyWithUid:(NSString *)uid transactionId:(NSString *)transactionId {
    if (uid == nil && transactionId == nil) { return nil; }
    return [NSString stringWithFormat:@"%@-%@", uid, transactionId];
}

/// 通过key更新订单重复次数
- (NSNumber *)orderRepeatForKey:(NSString *)repeatKey {
    if (repeatKey == nil) { return @0; }
    NSString *repeatString = [OPKKeychainItem valueForKey:repeatKey];
    if (repeatString == nil) { return @0; }
    NSNumber *repeatIntval = @([repeatString integerValue]);
    return repeatIntval;
}

/// 增加订单重复次数
- (void)addOrderRepeatForKey:(NSString *)repeatKey count:(NSInteger)count {
    if (repeatKey == nil || count == 0) { return; }
    NSString *repeatString = [OPKKeychainItem valueForKey:repeatKey];
    NSInteger repeat = 0;
    if (repeatString != nil && [repeatString integerValue] >= 0) {
        repeat = [repeatString integerValue];
    }
    repeat += 1;
    NSString *newRepeatString = [NSString stringWithFormat:@"%ld", (long)repeat];
    [OPKKeychainItem setValue:newRepeatString forKey:repeatKey];
}

/// 完成订单重复统计
- (void)finishOrderRepeatForKey:(NSString *)key {
    [OPKKeychainItem removeValueForKey:key];
}


// 从钥匙串获取当前用户已使用兑换码的次数
- (UInt8)currentUserLocalUsedCount:(NSArray<OPKTransactionItem*> *)transactionItems {
    UInt8 count = 0;
    for (OPKTransactionItem *item in transactionItems) {
        if (item.orderItem.productId == nil) { continue; }
        UInt8 _count = [self currentUserLocalUsedCountWithProductId:item.orderItem.productId];
        count = MAX(count, _count);
    }
    return count;
}

// 从钥匙串获取当前用户已使用兑换码的次数
- (UInt8)currentUserLocalUsedCountWithProductId:(NSString *)productId {
    NSString *uid = [[OpenSDK_LoginManager getInstance] curOpenId];
    if (uid == nil || productId == nil) { return 0; }
    NSString *key = [NSString stringWithFormat:@"used_count_%@_%@", uid, productId];
    NSString *countString = [OPKKeychainItem valueForKey:key];
    UInt8 count = [countString intValue];
    return count;
}

// 在钥匙串存储当前用户已使用兑换码的次数
- (void)setCurrentUserLocalUsedCount:(UInt8)count productId:(NSString *)productId {
    NSString *uid = [[OpenSDK_LoginManager getInstance] curOpenId];
    if (uid == nil || productId == nil) { return; }
    NSString *countString = [NSString stringWithFormat:@"%d", count];
    NSString *key = [NSString stringWithFormat:@"used_count_%@_%@", uid, productId];
    [OPKKeychainItem setValue:countString forKey:key];
}

// 从钥匙串获取当前用户是否已点击不再兑换
- (UInt8)currentUserLocalDiscardCount {
    NSString *uid = [[OpenSDK_LoginManager getInstance] curOpenId];
    if (uid == nil) { return 0; }
    NSString *key = [NSString stringWithFormat:@"discard_%@", uid];
    NSString *countString = [OPKKeychainItem valueForKey:key];
    UInt8 count = [countString intValue];
    return count;
}


// 在钥匙串存储当前用户已点击
- (void)setCurrentUserLocalDiscardCount:(UInt8)count {
    NSString *uid = [[OpenSDK_LoginManager getInstance] curOpenId];
    if (uid == nil) { return; }
    NSString *countString = [NSString stringWithFormat:@"%d", count];
    NSString *key = [NSString stringWithFormat:@"discard_%@", uid];
    [OPKKeychainItem setValue:countString forKey:key];
}



#pragma mark - 沙盒支付凭证

- (NSString *)receipt {
    NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *receiptData = [NSData dataWithContentsOfURL:receiptUrl];
    if (receiptData == nil) { return nil; }
    return [receiptData base64EncodedStringWithOptions:0];
}


@end


@implementation OPKOrderItem(ToUser)
- (OpenSDK_OrderInfo *)toOrderInfo {
    OpenSDK_OrderInfo *orderInfo=[[OpenSDK_OrderInfo alloc] initWithOrderID:self.orderId
                                                                   currency:self.currency
                                                              productAmount:self.productAmount
                                                                    product:self.productId
                                                                  payStatus:self.payStatus
                                                                    appData:self.payStatus
                                                                    payTime:(long)[self.payTime longLongValue]];
    return orderInfo;
}

@end
